package com.cloudcreativity.blyg.ui.cashier;

import android.app.Activity;
import android.databinding.ObservableField;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;

import com.baidu.tts.client.SpeechError;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener;
import com.baidu.tts.client.TtsMode;
import com.cloudcreativity.blyg.R;
import com.cloudcreativity.blyg.base.BaseBindingRecyclerViewAdapter;
import com.cloudcreativity.blyg.base.BaseDialogImpl;
import com.cloudcreativity.blyg.base.BaseModel;
import com.cloudcreativity.blyg.databinding.ActivityCashierBinding;
import com.cloudcreativity.blyg.databinding.ItemLayoutOpenOrderBinding;
import com.cloudcreativity.blyg.entity.BaseStringResult;
import com.cloudcreativity.blyg.entity.OpenOrderGoods;
import com.cloudcreativity.blyg.entity.PayOrder;
import com.cloudcreativity.blyg.sqlite.Goods;
import com.cloudcreativity.blyg.sqlite.utils.GoodsDaoUtils;
import com.cloudcreativity.blyg.utils.APIService;
import com.cloudcreativity.blyg.utils.AddGoodsUtils;
import com.cloudcreativity.blyg.utils.AlertDialogUtils;
import com.cloudcreativity.blyg.utils.AmountDialog;
import com.cloudcreativity.blyg.utils.DefaultObserver;
import com.cloudcreativity.blyg.utils.HttpUtils;
import com.cloudcreativity.blyg.utils.LogUtils;
import com.cloudcreativity.blyg.utils.PayDialog;
import com.cloudcreativity.blyg.utils.QueryGoodsDialog;
import com.cloudcreativity.blyg.utils.SPUtils;
import com.cloudcreativity.blyg.utils.ScanDialog;
import com.cloudcreativity.blyg.utils.StrUtils;
import com.cloudcreativity.blyg.utils.ToastUtils;
import com.cloudcreativity.blyg.utils.speech.Auth;
import com.cloudcreativity.blyg.utils.speech.OfflineResource;
import com.google.gson.Gson;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class CashierModel extends BaseModel<Activity, ActivityCashierBinding> {

    public ObservableField<String> key = new ObservableField<>();

    public BaseBindingRecyclerViewAdapter<OpenOrderGoods, ItemLayoutOpenOrderBinding> adapter;

    private GoodsDaoUtils goodsDaoUtils;

    private SpeechSynthesizer synthesizer;
    /**
     * 发布时请替换成自己申请的appId appKey 和 secretKey。注意如果需要离线合成功能,请在您申请的应用中填写包名。
     */
    private String appId;

    private String appKey;

    private String secretKey;

    private String sn; // 纯离线合成SDK授权码；离在线合成SDK免费，没有此参数

    // TtsMode.MIX; 离在线融合，在线优先； TtsMode.ONLINE 纯在线； TtsMode.OFFLINE 纯离线合成，需要纯离线SDK
    private TtsMode ttsMode = TtsMode.OFFLINE;

    CashierModel(final Activity context, final ActivityCashierBinding binding, BaseDialogImpl baseDialog) {
        super(context, binding, baseDialog);

        goodsDaoUtils = new GoodsDaoUtils(context);

        adapter = new BaseBindingRecyclerViewAdapter<OpenOrderGoods, ItemLayoutOpenOrderBinding>(context) {
            @Override
            protected int getLayoutResId(int viewType) {
                return R.layout.item_layout_open_order;
            }

            @Override
            protected void onBindItem(ItemLayoutOpenOrderBinding binding, final OpenOrderGoods item, final int position) {
                binding.setItem(item);
                binding.tvAmount.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        AmountDialog dialog = new AmountDialog(context, item.getName(), item.getUnit(), item.getSpecName());
                        dialog.setOnOkListener(new AmountDialog.OnOkListener() {
                            @Override
                            public void onOk(float amount) {
                                if(amount>item.getStock()){
                                    ToastUtils.showShortToast(context,"库存不足");
                                    return;
                                }
                                item.setAmount(amount);
                                item.calculate();
                                adapter.notifyItemChanged(position);
                                refresh();
                            }
                        });
                        dialog.show();
                    }
                });
                binding.tvDelete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        adapter.getItems().remove(position);
                        adapter.notifyItemChanged(position);
                        refresh();
                    }
                });
            }
        };

        binding.rcvGoods.setLayoutManager(new LinearLayoutManager(context,
                LinearLayoutManager.VERTICAL,
                false));

        //加上分割线
        DividerItemDecoration itemDecoration = new DividerItemDecoration(context,DividerItemDecoration.VERTICAL);
        itemDecoration.setDrawable(context.getResources().getDrawable(R.drawable.shape_item_divide));
        binding.rcvGoods.addItemDecoration(itemDecoration);

        binding.etDiscount.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                try {
                    if (TextUtils.isEmpty(editable)) {
                        discount = 0;
                    } else {
                        discount = new BigDecimal(editable.toString())
                                .multiply(new BigDecimal(100)).floatValue();
                    }
                    refresh();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        binding.etMoney.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (TextUtils.isEmpty(editable)) {
                    money = 0;
                } else {
                    money = new BigDecimal(editable.toString())
                            .multiply(new BigDecimal(100)).floatValue();
                }
                refresh();
            }
        });

        //初始化百度TTS服务
        initTTS();
    }

    private void initTTS(){
        //由于加载 tts语音model很耗时，所以，将该操作放入到子线程中
        new Thread(){
            @Override
            public void run() {
                try {
                    Auth.getInstance(context);
                } catch (Auth.AuthCheckException e) {
                    ToastUtils.showShortToast(context,e.getLocalizedMessage());
                    return;
                }

                appId = Auth.getInstance(context).getAppId();
                appKey = Auth.getInstance(context).getAppKey();
                secretKey = Auth.getInstance(context).getSecretKey();
                //因为百度tts离线服务 需要sn 但 sn只支持一个设备一个sn 所以是后台配置，不在auth.properties中
                sn = SPUtils.get().getUser().getBaiduTtsCode();

                synthesizer = SpeechSynthesizer.getInstance();
                synthesizer.setParam(SpeechSynthesizer.PARAM_AUTH_SN,sn);

                synthesizer.setContext(context);
                synthesizer.setApiKey(appKey,secretKey);
                synthesizer.setAppId(appId);

                synthesizer.auth(ttsMode);

                //授权为离线模式
                synthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME,"15");
                synthesizer.setParam(SpeechSynthesizer.PARAM_SPEED,"6");

                // 离线资源文件， 从assets目录中复制到临时目录，需要在initTTs方法前完成
                OfflineResource offlineResource = createOfflineResource(OfflineResource.VOICE_FEMALE);

                // 声学模型文件路径 (离线引擎使用), 请确认下面两个文件存在
                synthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE,offlineResource.getTextFilename());
                synthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE,offlineResource.getModelFilename());

                synthesizer.setSpeechSynthesizerListener(new SpeechSynthesizerListener() {
                    @Override
                    public void onSynthesizeStart(String s) {
                        LogUtils.e("xuxiwu","开始异步"+s);
                    }

                    @Override
                    public void onSynthesizeDataArrived(String s, byte[] bytes, int i, int i1) {
                        LogUtils.e("xuxiwu","异步接受数据"+s);
                    }

                    @Override
                    public void onSynthesizeFinish(String s) {
                        LogUtils.e("xuxiwu","异步结束"+s);
                    }

                    @Override
                    public void onSpeechStart(String s) {
                        LogUtils.e("xuxiwu","开始讲话"+s);
                    }

                    @Override
                    public void onSpeechProgressChanged(String s, int i) {

                    }

                    @Override
                    public void onSpeechFinish(String s) {
                        LogUtils.e("xuxiwu","讲话结束"+s);
                    }

                    @Override
                    public void onError(String s, SpeechError speechError) {
                        LogUtils.e("xuxiwu","系统异常"+s);
                        LogUtils.e("xuxiwu",speechError.description);
                    }
                });
                int i = synthesizer.initTts(ttsMode);
                if(i!=0){
                    context.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtils.showShortToast(context,"初始化失败");
                        }
                    });
                }
            }
        }.start();
    }

    private OfflineResource createOfflineResource(String voiceType) {
        OfflineResource offlineResource = null;
        try {
            offlineResource = new OfflineResource(context, voiceType);
        } catch (IOException e) {
            // IO 错误自行处理
            e.printStackTrace();
        }
        return offlineResource;
    }

    @Override
    protected void initView() {

    }

    @Override
    protected void initData() {

    }

    public void onBack() {
        context.finish();
    }

    public void onClear() {
        adapter.getItems().clear();
        discount = 0;
        money = 0;
        binding.etMoney.setText(null);
        binding.etDiscount.setText(null);
        refresh();
    }

    public void onQueryClick() {
        QueryGoodsDialog dialog = new QueryGoodsDialog(context);
        dialog.show();
        dialog.setOnItemClickListener(new QueryGoodsDialog.OnItemClickListener() {
            @Override
            public void onItemClick(final Goods goods) {
                pushGoods(goods, 1);
            }
        });
    }

    //扫码回掉
    void onCode(final String code) {
        final Goods goods = goodsDaoUtils.queryByCode(code);
            if(goods==null){
                AlertDialogUtils alertDialogUtils = new AlertDialogUtils(context,"提示",
                        "没有该商品，是否要添加？");
                alertDialogUtils.setOnResultListener(new AlertDialogUtils.OnResultListener() {
                    @Override
                    public void onOk() {
                        AddGoodsUtils addGoodsUtils = new AddGoodsUtils(context,code,getBaseDialog());
                        addGoodsUtils.setOnOkListener(new AddGoodsUtils.OnOkListener() {
                            @Override
                            public void onOk(final Goods goods) {
                                boolean result = goodsDaoUtils.insert(goods);
                                if(!result){
                                    ToastUtils.showShortToast(context,"该商品已存在");
                                    return;
                                }
                                //将商品数据保存到远程服务器
                                OkHttpClient client = new OkHttpClient();
                                FormBody body = new FormBody.Builder()
                                        .addEncoded("barCode",goods.getBarCode())
                                        .addEncoded("brandName", TextUtils.isEmpty(goods.getBrandName())?"":goods.getBrandName())
                                        .addEncoded("categoryOneId",String.valueOf(goods.getCategoryOneId()))
                                        .addEncoded("categoryTwoId",String.valueOf(goods.getCategoryTwoId()))
                                        .addEncoded("name",goods.getName())
                                        .addEncoded("price",String.valueOf(goods.getPrice()))
                                        .addEncoded("specName",TextUtils.isEmpty(goods.getSpecName())?"":goods.getSpecName())
                                        .addEncoded("unit",TextUtils.isEmpty(goods.getUnit())?"":goods.getUnit())
                                        .build();
                                Request request = new Request.Builder()
                                        .url(APIService.HOST_APP+"/base/addBaseGoods")
                                        .post(body)
                                        .build();
                                Call call = client.newCall(request);
                                call.enqueue(new Callback() {
                                    @Override
                                    public void onFailure(Call call, IOException e) {

                                    }

                                    @Override
                                    public void onResponse(Call call, Response response) throws IOException {
                                        String result = response.body().string();
                                        LogUtils.e("xuxiwu",result);
                                        try {
                                            JSONObject object = new JSONObject(result);
                                            if(object.getInt("status")==1){
                                                //添加成功，将返回的信息保存
                                                JSONObject info = object.getJSONObject("info");
                                                long goodsId = info.getLong("goodsId");
                                                int brandId = info.getInt("brandId");
                                                goods.setId(goodsId);
                                                goods.setBrandId(brandId);
                                                goodsDaoUtils.update(goods);
                                            }
                                        } catch (JSONException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                });
                            }
                        });
                        addGoodsUtils.show();
                    }

                    @Override
                    public void onCancel() {

                    }
                });
                alertDialogUtils.show();
                return;
            }
        //默认给一个数量
        pushGoods(goods, 1);

    }

    private void pushGoods(Goods goods, float amount) {

        for (int i = 0; i < adapter.getItemCount(); i++) {
            if (adapter.getItems().get(i).getLid().equals(goods.getLid())) {

                //同一商品，只修改数量
                if(adapter.getItems().get(i).getStock()<adapter.getItems().get(i).getAmount()+amount){
                    ToastUtils.showShortToast(context,"库存不足");
                    return;
                }
                adapter.getItems().get(i).setAmount(adapter.getItems().get(i).getAmount() + amount);
                adapter.getItems().get(i).calculate();
                adapter.notifyItemChanged(i);
                refresh();
                return;
            }
        }

        if(amount>goods.getStock()){
            ToastUtils.showShortToast(context,"库存不足");
            return;
        }

        OpenOrderGoods openOrderGoods = new OpenOrderGoods();
        openOrderGoods.setId(goods.getId());
        openOrderGoods.setLid(goods.getLid());
        openOrderGoods.setCategoryOneId(goods.getCategoryOneId());
        openOrderGoods.setCategoryTwoId(goods.getCategoryTwoId());
        openOrderGoods.setUnit(goods.getUnit());
        openOrderGoods.setUnitId(goods.getUnitId());
        openOrderGoods.setSpecName(goods.getSpecName());
        openOrderGoods.setBarCode(goods.getBarCode());
        openOrderGoods.setPrice(goods.getPrice());
        openOrderGoods.setBrandId(goods.getBrandId());
        openOrderGoods.setStock(goods.getStock());
        openOrderGoods.setBrandName(goods.getBrandName());
        openOrderGoods.setName(goods.getName());
        openOrderGoods.setAmount(amount);

        openOrderGoods.calculate();
        adapter.getItems().add(openOrderGoods);

        refresh();
    }

    // 计算价格信息
    //应收
    private float totalMoney;
    //折扣
    private float discount;
    //实收
    private float money;
    //找零
    private float zeroMoney;
    //总计
    private float finalMoney;

    private void refresh() {

        totalMoney = 0;
        finalMoney = 0;

        for (OpenOrderGoods goods : adapter.getItems()) {
            totalMoney += goods.getAmount() * goods.getPrice();
        }

        if (money > 0) {
            //有实收，需要计算找零
            zeroMoney = new BigDecimal(money)
                    .subtract(new BigDecimal(totalMoney)
                            .subtract(new BigDecimal(discount))).floatValue();
        } else {
            zeroMoney = 0;
        }

        finalMoney = new BigDecimal(totalMoney).subtract(new BigDecimal(discount)).floatValue();

        //设置数据
        binding.tvTotalMoney.setText(String.valueOf(StrUtils.get2BitDecimal(totalMoney / 100f)));
        binding.tvFinal.setText(String.valueOf(StrUtils.get2BitDecimal(finalMoney / 100f)));
        binding.tvZero.setText(String.valueOf(StrUtils.get2BitDecimal(zeroMoney / 100f)));
    }

    public void onMoneyClick() {
        if (adapter.getItemCount() <= 0 || finalMoney <0) return;
        submitOrder(1,
                new BigDecimal(totalMoney).intValue(),
                new BigDecimal(discount).intValue(),
                new BigDecimal(finalMoney).intValue(),
                adapter.getItems());
    }

    public void onMobileClick() {
        if (adapter.getItemCount() <= 0 || finalMoney <= 0) return;
        submitOrder(2,
                new BigDecimal(totalMoney).intValue(),
                new BigDecimal(discount).intValue(),
                new BigDecimal(finalMoney).intValue(),
                adapter.getItems());
    }

    // payWay 1 现金支付 2 扫码支付
    private void submitOrder(final int payWay, final int totalMoney,
                             final int discountMoney, final int finalMoney, final List<OpenOrderGoods> goods) {
        final PayDialog payDialog = new PayDialog(context);
        if (payWay == 1) {
            payDialog.ordering();
            payDialog.show();

            int shopId = SPUtils.get().getUser().getShopId();
            HttpUtils.getInstance().addOrder(payWay, shopId, totalMoney, totalMoney, discountMoney, finalMoney,
                    new Gson().toJson(goods))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new DefaultObserver<PayOrder>(getBaseDialog(), false) {
                        @Override
                        public void onSuccess(PayOrder t) {
                            //下单成功，更新库存
                            for (OpenOrderGoods g : goods) {
                                goodsDaoUtils.updateStock(g.getLid(), g.getAmount());
                            }
                            payDialog.success();
                            onClear();
                        }

                        @Override
                        public void onFail(ExceptionReason msg) {
                            super.onFail(msg);
                            payDialog.failed();
                        }
                    });
        } else {
            //扫码支付
            ScanDialog dialog = new ScanDialog(context);
            dialog.setOnOkListener(new ScanDialog.OnOkListener() {
                @Override
                public void onOk(final String code) {
                    LogUtils.e("xuxiwu", "扫码回掉一次....");
                    final int shopId = SPUtils.get().getUser().getShopId();
                    payDialog.ordering();
                    payDialog.show();
                    HttpUtils.getInstance().addOrder(payWay, shopId, totalMoney, totalMoney, discountMoney, finalMoney,
                            new Gson().toJson(goods))
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new DefaultObserver<PayOrder>(getBaseDialog(), false) {
                                @Override
                                public void onSuccess(PayOrder t) {
                                    payDialog.paying();
                                    //下单成功，发起支付 t 返回的信息就是订单编号
                                    HttpUtils.getInstance().pay(finalMoney,
                                            t.getInfo().getOrderId(),
                                            t.getInfo().getOrderNo(), code, shopId)
                                            .subscribeOn(Schedulers.io())
                                            .observeOn(AndroidSchedulers.mainThread())
                                            .subscribe(new DefaultObserver<BaseStringResult>(getBaseDialog(), false) {
                                                @Override
                                                public void onSuccess(BaseStringResult t) {
                                                    //下单成功，更新库存j
                                                    for (OpenOrderGoods g : goods) {
                                                        goodsDaoUtils.updateStock(g.getLid(), g.getAmount());
                                                    }
                                                    payDialog.paySuccess();
                                                    onClear();
                                                    //播放收款语音
                                                    playAudio(finalMoney,t.getInfo());
                                                }

                                                @Override
                                                public void onFail(ExceptionReason msg) {
                                                    payDialog.payError();
                                                }
                                            });
                                }

                                @Override
                                public void onFail(ExceptionReason msg) {
                                    super.onFail(msg);
                                    payDialog.failed();
                                }
                            });
                }
            });
            dialog.show();
        }


    }

    private void playAudio(int finalMoney, String info) {
        double money = StrUtils.get2BitDecimal(finalMoney/100f);
        String voice = "收款成功";
        switch (info){
            case "2":
                voice = context.getResources().getString(R.string.voice_weixin,money);
                break;
            case "3":
                voice = context.getResources().getString(R.string.voice_alipay,money);
                break;
            case "4":
                voice = context.getResources().getString(R.string.voice_card,money);
                break;
        }
        synthesizer.speak(voice);
    }

    void onDestroy() {
        if(synthesizer!=null){
            synthesizer.stop();
            synthesizer.release();
        }
        synthesizer = null;
    }
}
